﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace EmbeddedSensorCloud.Command
{
    public abstract class CommandBase
    {
        public delegate void LogEventHandler(string message);
        public static event LogEventHandler Logged;

        public abstract string Description { get; }
        public abstract string Name { get; }
        public abstract string Syntax { get; }
        public abstract string RequiredArgumentRegex { get; }

        public CommandBase()
        {
            if (string.IsNullOrEmpty(this.Name))
            {
                throw new ArgumentException("Name cannot be null or empty", "Name");
            }
            
            if (this.RequiredArgumentRegex == null)
            {
                throw new ArgumentException("RequiredArgumentRegex cannot be null", "RequiredArgumentRegex");
            }
        }

        protected abstract void execute(string[] param);

        protected void RaiseLogged(string message)
        {
            if (string.IsNullOrWhiteSpace(message))
            {
                throw new ArgumentException("Message cannot be null, empty or whitespaced");
            }

            if (CommandBase.Logged != null)
            {
                CommandBase.Logged(message);
            }
        }

        public void Execute(string param)
        {
            if (string.IsNullOrWhiteSpace(param))
            {
                throw new ArgumentException("Command code cannot be null, empty or whitespaced");
            }

            string[] splits = ArgumentResolver.SplitArguments(param);
            string[] args = new string[splits.Length - 1];
            for (int i = 1; i < splits.Length; i++)
            {
                args[i - 1] = splits[i];
            }

            this.execute(args);
        }

        public bool CanExecute(string param)
        {
            if (string.IsNullOrWhiteSpace(param))
            {
                return false;
            }

            string[] splits = ArgumentResolver.SplitArguments(param);

            // Invalid string or no suitable exec name
            if (!splits.Any() || !splits[0].Equals(this.Name, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }

            var space = string.IsNullOrWhiteSpace(this.RequiredArgumentRegex) ? "" : " ";
            var matchStr = string.Format("^{0}{1}{2}$", this.Name, space, this.RequiredArgumentRegex);
            var match = Regex.Match(param, matchStr, RegexOptions.Singleline | RegexOptions.IgnoreCase);
            return match.Success;
        }

        public override string ToString()
        {
            return string.Format("   {0}  {1}", this.Syntax, this.Description);
        }
    }
}
